// Image Middlerware
import multer, { type FileFilterCallback } from "multer"
import sharp from "sharp"
import type { NextFunction, Response, Request } from "express";
import AppError from "../class/AppError.js"
import { catchAsync, randomChars, getClientIp, getFilePrefix, getFileSuffix } from "../util/index.js";
import sql from "../sql/index.js"
import fs from "fs-extra"

// 测试上传的文件是否为图片
const multerFilterer = (req: Request, file: Express.Multer.File, cb: FileFilterCallback) => {
  if (file.mimetype.startsWith('image')) {
    cb(null, true)
  } else {
    cb(new AppError(400, 'Not an image! Please upload images'), false)
  }
}

// 处理图片中间件
export const handleImage = multer({
  storage: multer.memoryStorage(),    // 将图片转化为 buffer 流
  fileFilter: multerFilterer,
  limits: {
    fileSize: 6 * 1024 * 1024,    // 单位字节
  }
}).array('img')

// 调整图片大小
export const resizeUserPhoto = catchAsync(async (req: Request<any, any, { time: string }>, res: Response, next: NextFunction) => {
  if (!req.files) return next(new AppError(400, 'File not found'));

  req.saveImg = [];
  const timeArr = req.body.time.split(",");
  // 同步获取文件名
  (req.files as Array<Express.Multer.File>).forEach((file, index) => {
    const expired = timeArr[index]
    let time = "permanent"
    // 获取保存时间
    if (expired) {
      time = expired === "*" ? "permanent" : timeArr[index]
    }
    const fileName = getFilePrefix(file.originalname) || "unknow-name"
    // 生成唯一文件名
    const FILE_NAME = `${randomChars(18)}-${time}-${fileName}.webp`
    req.saveImg.push(FILE_NAME)
  });
  // 异步创建文件
  (req.files as Array<Express.Multer.File>).forEach(async (file, index) => {
    // 保存图片
    await sharp(file.buffer)
      // .resize(500, 500)    // 裁剪图片, 设置为500 x 500
      .toFormat('webp')
      .webp({ quality: 90 })
      .toFile(`uploads/${req.saveImg[index]}`)
  });

  next()
})

// 判断用户存储数量
export const protectStorage = (req: Request, res: Response, next: NextFunction) => {
  // 1 读取数据
  const data = sql.read(req.clientIp)
  // 2 判断超过最大数量
  if (data.length >= Number(process.env.MAX_NUM)) {
    next(new AppError(202, `The number of uploaded images has exceeded ${process.env.MAX_NUM}`))
  }
  // 3 正常继续执行
  req.storageSize = data.length
  next()
}

// 判断图片是否过期 且 文件名后缀为 webp 的文件
export const judgeImgVilad = (req: Request, res: Response, next: NextFunction) => {
  const reg = /-([\d|permanent]+)-/
  const img = req.originalUrl

  const matchs = (img as string).match(reg) || []
  const fileType = getFileSuffix(img)

  if (fileType != "webp") {
    return next(new AppError(400, "Img type not webp"))
  }
  // 判断
  let expiredTime = matchs[1]
  // 永久
  if (expiredTime === "permanent") return next();
  // 有时间
  else if (expiredTime) {
    if (Date.now() <= Number(expiredTime)) {
      return next()
    }
    return next(new AppError(400, "Img expired"))
  }
  // unknow
  next(new AppError(400, "Img Unknow"))
}
